package com.quiz.quazz;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.quiz.quazz.util.IpConfigUtil;

public class GameBrowserActivity extends Activity {

	private TextView textViewGameCounterNumber;

	private ListView gameListView;

	private List<InetAddress> foundDevices;

	private int counter = 0;

	private ProgressBar progressBarScan;

	private GamesArrayAdapter adapter;

	@Override
	public void onCreate(final Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_game_browser);

		textViewGameCounterNumber = (TextView) findViewById(R.id.labelGameCounterNumber);
		progressBarScan = (ProgressBar) findViewById(R.id.progressBarScan);
		progressBarScan.setMax(255);
		progressBarScan.setVisibility(View.INVISIBLE);

		gameListView = (ListView) findViewById(R.id.listViewGames);
		gameListView.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> arg0, final View arg1, final int arg2, long arg3) {

				LayoutInflater li = LayoutInflater.from(GameBrowserActivity.this);
				View promptsView = li.inflate(R.layout.prompt_port, null);

				AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(GameBrowserActivity.this);

				alertDialogBuilder.setView(promptsView);
				alertDialogBuilder.setMessage("Please enter the server port!");

				final EditText userInput = (EditText) promptsView.findViewById(R.id.editTextInputPort);

				alertDialogBuilder.setCancelable(false).setPositiveButton("OK", new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int id) {
						// String ip = (String) ((TextView) arg1).getText().subSequence(1, ((TextView) arg1).getText().length());
						String serverIp = adapter.getItem(arg2).getHostAddress();
						int port = Integer.parseInt(userInput.getText().toString());
						// new Client(ip, port, IpConfigUtil.getIPAddress(true));

						Intent intent = new Intent(GameBrowserActivity.this, LobbyActivity.class);
						intent.putExtra("isServer", false);
						intent.putExtra("serverIp", serverIp);
						intent.putExtra("serverPort", port);
						intent.putExtra("playerName", getIntent().getStringExtra("playerName"));
						startActivity(intent);
					}
				}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int id) {
						dialog.cancel();
					}
				});

				AlertDialog alertDialog = alertDialogBuilder.create();

				alertDialog.show();
			}
		});

		Button buttonRefresh = (Button) findViewById(R.id.buttonRefresh);
		buttonRefresh.setCompoundDrawablesWithIntrinsicBounds(android.R.drawable.ic_popup_sync, 0, 0, 0);
		buttonRefresh.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {
				runOnUiThread(new Runnable() {
					@Override
					public void run() {
						gameListView.setAdapter(null);
						textViewGameCounterNumber.setText("0");
					}
				});
				getConnectedDevices(IpConfigUtil.getIPAddress(true));
			}
		});
	}

	@Override
	protected void onPostCreate(Bundle savedInstanceState) {
		super.onPostCreate(savedInstanceState);
		getConnectedDevices(IpConfigUtil.getIPAddress(true));
	}

	private class GamesArrayAdapter extends ArrayAdapter<InetAddress> {

		HashMap<InetAddress, Integer> gameMap = new HashMap<InetAddress, Integer>();

		public GamesArrayAdapter(Context context, int textViewResourceId, List<InetAddress> games) {
			super(context, textViewResourceId, foundDevices);
			for (int i = 0; i < games.size(); ++i) {
				gameMap.put(games.get(i), i);
			}
		}

		@Override
		public long getItemId(int position) {
			InetAddress item = getItem(position);
			return gameMap.get(item);
		}

		@Override
		public boolean hasStableIds() {
			return true;
		}

	}

	private List<InetAddress> getConnectedDevices(String iPAddress) {
		foundDevices = new ArrayList<InetAddress>();
		final String[] myIPArray = iPAddress.split("\\.");

		for (int i = 0; i <= 255; i++) {
			final int ip = i;

			new Thread(new Runnable() {

				@Override
				public void run() {
					pingIpRange(new ArrayList<InetAddress>(), myIPArray, ip, 0);
				}
			}).start();
		}
		return foundDevices;
	}

	private ArrayList<InetAddress> pingIpRange(ArrayList<InetAddress> ret, String[] myIPArray, int startIp, int endIp) {
		InetAddress currentPingAddr;

		try {

			// build the next IP address
			currentPingAddr =
				InetAddress.getByName(myIPArray[0] + "." + myIPArray[1] + "." + myIPArray[2] + "." + Integer.toString(startIp));

			if (currentPingAddr.isReachable(4000)) {
				foundDevices.add(currentPingAddr);
			}
			updateScanProgress();
		} catch (UnknownHostException ex) {
			ex.printStackTrace();
		} catch (IOException ex) {
			ex.printStackTrace();
		}

		return ret;
	}

	private void updateScanProgress() {
		runOnUiThread(new Runnable() {
			@Override
			public void run() {
				progressBarScan.setVisibility(View.VISIBLE);
				if (counter == 255) {
					updateGameList();
					counter = 0;
					progressBarScan.setProgress(counter);
					progressBarScan.setVisibility(View.INVISIBLE);
				} else {
					counter++;
					progressBarScan.setProgress(counter);
				}
			}
		});
	}

	private void updateGameList() {
		adapter = new GamesArrayAdapter(GameBrowserActivity.this, android.R.layout.simple_list_item_1, foundDevices);

		runOnUiThread(new Runnable() {
			@Override
			public void run() {
				gameListView.setAdapter(adapter);
				textViewGameCounterNumber.setText(foundDevices.size() + "");
			}
		});
	}
}